import csv
from collections import defaultdict
from datetime import datetime,date
import calendar

from django.http import HttpResponse
from django.shortcuts import render ,redirect
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from expense.models import Category, Expense
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.db.models import Q
from io import BytesIO
import openpyxl
from django.http.response import FileResponse,JsonResponse
from reportlab.pdfgen import canvas

from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont

# Create your views here.

@login_required(login_url='login')
def index(request):
    page =int(request.GET.get('page', 1))
    search = request.GET.get('search', '').strip()
    if not search:
        expenses = Expense.objects.filter(owner=request.user).all()
    else:
        expenses = Expense.objects.filter(
           Q(owner=request.user),
           Q(amount__startswith=search) |
           Q(category__icontains=search) |
           Q(description__icontains=search) |
           Q(date__startswith=search),

        )


    paginator = Paginator(expenses, 10)  # 每页显示10条记录
    context = {'page_obj': paginator.get_page(page)}

    return render(request, 'expense/index.html', context)

@login_required(login_url='login')
def add_expense(request):
    context = {
        'categories': Category.objects.all(),
        'values': request.POST,
    }

    if request.method == 'GET':
        return render(request, 'expense/add_expense.html', context=context)
    else:
        amount = request.POST['amount']
        category = request.POST['category']
        if not amount:
            messages.error(request, '数量不能为空')
            return render(request, 'expense/add_expense.html', context=context)
        if not category:
            messages.error(request, '类别不能为空')
            return render(request, 'expense/add_expense.html', context=context)

        Expense.objects.create(
            category=category,
            amount=amount,
            description=request.POST['description'],
            date=request.POST['date'],
            owner=request.user,
        )

        messages.success(request, '添加成功')
        return redirect(to='expense')

@login_required(login_url='login')
def edit_expense(request, id):
    expense = Expense.objects.get(pk=id)
    categories = Category.objects.all()
    context = {
        'expense': expense,
        'categories': categories,
        'values': expense,
    }
    if request.method == 'GET':
        return render(request, 'expense/edit_expense.html', context=context)
    else:
        context['value'] = request.POST
        amount = request.POST['amount']
        category = request.POST['category']
        if not amount:
            messages.error(request, '数量不能为空')
            return render(request, 'expense/edit_expense.html', context=context)
        if not category:
            messages.error(request, '类别不能为空')
            return render(request, 'expense/edit_expense.html', context=context)

        expense.amount = amount
        expense.category = category
        expense.description = request.POST['description']
        date = request.POST['date']
        if not date:
            expense.date = datetime.today()
        else:
            expense.date = date
        expense.save()
        messages.success(request, '修改成功')
        return redirect(to='expense')

@login_required(login_url='login')
def delete_expense(request, id):
    Expense.objects.get(pk=id).delete()
    messages.success(request, '删除成功')
    return redirect(to='expense')

@login_required(login_url='login')
def download_csv(request):
    response = HttpResponse(
        content_type='text/csv',
        headers={
            'Content-Disposition': 'attachment; filename=expenses.csv'
        }
    )

    writer = csv.writer(response)
    writer.writerow(['金额', '类型', '日期', '描述'])
    for item in Expense.objects.filter(owner=request.user).all():
        row = [item.amount,item.category, str(item.date), item.description]
        writer.writerow(row)

    return response

@login_required(login_url='login')
def download_pdf(request):
    # 注册中文字体
    pdfmetrics.registerFont(TTFont('SimSun', 'simsun.ttc'))  # 宋体
    pdfmetrics.registerFont(TTFont('SimHei', 'simhei.ttf'))  # 黑体

    bio = BytesIO()
    pdf = canvas.Canvas(bio)

    # 设置标题
    pdf.setFont("SimHei", 16)  # 使用黑体
    pdf.drawString(100, 800, "我的消费记录")

    # 设置表头
    pdf.setFont("SimHei", 12)  # 使用黑体
    pdf.drawString(100, 770, "金额")
    pdf.drawString(200, 770, "类型")
    pdf.drawString(300, 770, "日期")
    pdf.drawString(400, 770, "描述")

    # 添加表格线
    pdf.line(100, 765, 500, 765)

    # 设置内容字体
    pdf.setFont("Helvetica", 10)

    expenses = Expense.objects.filter(owner=request.user).all()
    y_position = 750
    for item in expenses:
        # 绘制每行数据
        pdf.setFont("SimHei", 12)  # 使用黑体
        pdf.drawString(100, y_position, str(item.amount))
        pdf.drawString(200, y_position, item.category)
        pdf.drawString(300, y_position, str(item.date))
        pdf.drawString(400, y_position, item.description)

        # 添加行分隔线
        pdf.line(100, y_position - 5, 500, y_position - 5)

        y_position -= 20

        # 如果内容超出页面，创建新页面
        if y_position < 50:
            pdf.showPage()
            y_position = 750
            # 在新页面添加表头
            pdf.setFont("Helvetica-Bold", 12)
            pdf.drawString(100, 770, "金额")
            pdf.drawString(200, 770, "类型")
            pdf.drawString(300, 770, "日期")
            pdf.drawString(400, 770, "描述")
            pdf.line(100, 765, 500, 765)
            pdf.setFont("Helvetica", 10)

    pdf.showPage()
    pdf.save()
    bio.seek(0)
    return FileResponse(bio, as_attachment=True, filename='expenses.pdf')


@login_required(login_url='login')
def download_excel(request):
    bio = BytesIO()
    # 创建一个workbook对象，而且会在workbook中至少创建一个表worsheet
    wb = openpyxl.Workbook()
    # 获取当前活跃的worksheet,默认就是第一个worksheet
    ws = wb.active
    title = ['金额', '类型', '日期', '描述']
    data = [
        [item.amount, item.category, str(item.date), item.description]
        for item in Expense.objects.filter(owner=request.user).all()
    ]
    data.insert(0, title)
    for row in range(0, len(data)):
        for col in range(0, len(data[row])):
            ws.cell(row=row + 1, column=col + 1, value=data[row][col])
    wb.save(bio)
    bio.seek(0) # 移动指针到文件头 一定要移动到文件头，否则会出现空白文件

    ws.append(title)
    return FileResponse(bio, as_attachment=True,filename='expenses.xlsx')

@login_required(login_url='login')
def index_stats(request):
    # 本月所有支出数据
    start_date = date.today().replace(day=1)
    end_date = start_date.replace(
        day=calendar.monthrange(start_date.year, start_date.month)[1]
    )
    expenses = Expense.objects.filter(owner=request.user, date__range=(start_date, end_date)).all()
    # 统计每个类型的支出金额
    category_dict = defaultdict(int)
    day_dict = defaultdict(int)
    for item in expenses:
        category_dict[item.category] += item.amount
        day_dict[item.date.day] += item.amount

    day_list = sorted(day_dict.keys(), key=lambda x: x)

    response_date = {
        'category': [{'name': key, 'value': value} for key, value in category_dict.items()],
        'daily': {
            'keys': day_list,
            'values': [day_dict[key] for key in day_list],
        }
    }
    return JsonResponse(response_date)

@login_required(login_url='login')
def expense_summary(request):
    today = date.today()
    start_date = today.replace(year=today.year - 1 , month=1, day=1)

    today_sum_stats = {
        'title': '今天',
        'count':0,
        'sum':0
    }
    this_month_sum_stats = {
        'title': '本月',
        'count': 0,
        'sum': 0
    }
    this_year_stats = {
        'title': '今年',
        'count': 0,
        'sum': 0
    }
    last_year_stats = {
        'title': '去年',
        'count': 0,
        'sum': 0
    }

    expenses = Expense.objects.filter(
        owner=request.user,
        date__gte=start_date
    ).all()
    for item in expenses:

        if item.date == today:
            today_sum_stats['count'] += 1
            today_sum_stats['sum'] += item.amount
        if item.date >= today.replace(day=1):
            this_month_sum_stats['count'] += 1
            this_month_sum_stats['sum'] += item.amount
        if item.date >= today.replace(month=1, day=1):
            this_year_stats['count'] += 1
            this_year_stats['sum'] += item.amount
        if item.date >= start_date:
            last_year_stats['count'] += 1
            last_year_stats['sum'] += item.amount

    context = {
        'sum_stats_list': [
           today_sum_stats,
           this_month_sum_stats,
           this_year_stats,
           last_year_stats,
       ],
        'title': '消费统计'
    }
    return render(request, 'expense/expense_summary.html', context)

@login_required(login_url='login')
def expense_s1(request):
    # 今年各类型支出占比饼图
    expenses = Expense.objects.filter(owner=request.user,date__year=date.today().year)
    category_dict = defaultdict(int)
    for item in expenses:
        category_dict[item.category] += item.amount
    data = [{'name': key, 'value': value} for key, value in category_dict.items()]

    return JsonResponse(data, safe=False)

@login_required(login_url='login')
def expense_s2(request):
    # 今年每月支出柱状图
    expenses = Expense.objects.filter(owner=request.user, date__year=date.today().year)
    category_dict = defaultdict(int)
    for item in expenses:
        category_dict[item.category] += item.amount
    data = {
        'captions': list(category_dict.keys()),
        'values': [category_dict[k] for k in category_dict],  # 按月份排序
    }
    return JsonResponse(data)

@login_required(login_url='login')
def expense_s3(request):
    # 今年每月支出金额 柱状图
    expenses = Expense.objects.filter(owner=request.user, date__year=date.today().year)
    month_expenses = {str(m+1): 0 for m in range(12)}
    for item in expenses:
        month_expenses[str(item.date.month)] += item.amount
    values = [month_expenses[m] for m in month_expenses]
    max_value_index = values.index(max(values))
    data = {
        'captions': list(month_expenses.keys()),
        'values': values,
        'max_value_index': max_value_index,
    }
    return JsonResponse(data)